#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
微信订阅号永久素材管理工具
基于现有PHP代码中的配置信息开发
"""

import requests
import json
import time
import os
from datetime import datetime

class WeChatMaterial:
    def __init__(self):
        # 从PHP代码中获取的配置信息
        self.appid = "wx73dfb63aa6776133"
        self.appsecret = "571dce27b4a603695da033b83a1d414e"
        self.access_token_file = "access_token.txt"
        
    def get_access_token(self):
        """
        获取access_token，有效期7200s
        优先从文件读取，过期则重新获取
        """
        try:
            # 尝试从文件读取token
            if os.path.exists(self.access_token_file):
                with open(self.access_token_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    
                # 检查是否过期
                if data.get('expire_time', 0) > time.time():
                    return data.get('access_token')
            
            # 重新获取token
            url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={self.appid}&secret={self.appsecret}"
            response = requests.get(url, timeout=30)
            result = response.json()
            
            if 'access_token' in result:
                access_token = result['access_token']
                # 保存到文件，提前200秒过期以确保安全
                data = {
                    'access_token': access_token,
                    'expire_time': time.time() + 7000
                }
                
                with open(self.access_token_file, 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=2)
                
                return access_token
            else:
                print(f"获取access_token失败: {result}")
                return None
                
        except Exception as e:
            print(f"获取access_token异常: {e}")
            return None
    
    def get_material_count(self):
        """
        获取素材总数
        """
        access_token = self.get_access_token()
        if not access_token:
            return None
            
        url = f"https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token={access_token}"
        
        try:
            response = requests.get(url, timeout=30)
            result = response.json()
            return result
        except Exception as e:
            print(f"获取素材总数失败: {e}")
            return None
    
    def get_material_list(self, material_type="image", offset=0, count=20):
        """
        获取永久素材列表
        
        Args:
            material_type: 素材类型 image(图片)/voice(语音)/video(视频)/news(图文)
            offset: 偏移量，表示从全部素材中的该偏移位置开始返回
            count: 返回素材的数量，取值在1到20之间
        """
        access_token = self.get_access_token()
        if not access_token:
            return None
            
        url = f"https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token={access_token}"
        
        data = {
            "type": material_type,
            "offset": offset,
            "count": count
        }
        
        try:
            response = requests.post(
                url, 
                data=json.dumps(data, ensure_ascii=False).encode('utf-8'),
                headers={'Content-Type': 'application/json; charset=utf-8'},
                timeout=30
            )
            result = response.json()
            return result
        except Exception as e:
            print(f"获取素材列表失败: {e}")
            return None
    
    def get_all_materials(self, material_type="image"):
        """
        获取所有指定类型的永久素材
        """
        all_materials = []
        offset = 0
        count = 20  # 每次最多获取20个
        
        print(f"开始获取所有{material_type}类型的永久素材...")
        
        while True:
            print(f"正在获取第 {offset + 1} - {offset + count} 个素材...")
            
            result = self.get_material_list(material_type, offset, count)
            if not result:
                break
                
            if 'item' in result:
                materials = result['item']
                if not materials:  # 没有更多素材
                    break
                    
                all_materials.extend(materials)
                print(f"已获取 {len(materials)} 个素材")
                
                # 如果返回的素材数量少于请求数量，说明已经是最后一页
                if len(materials) < count:
                    break
                    
                offset += count
            else:
                print(f"获取失败: {result}")
                break
        
        print(f"总共获取到 {len(all_materials)} 个{material_type}素材")
        return all_materials
    
    def save_materials_to_file(self, materials, material_type, filename=None):
        """
        保存素材信息到文件
        """
        if not filename:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"wechat_materials_{material_type}_{timestamp}.json"
        
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump({
                    'type': material_type,
                    'count': len(materials),
                    'update_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    'materials': materials
                }, f, ensure_ascii=False, indent=2)
            
            print(f"素材信息已保存到文件: {filename}")
            return filename
        except Exception as e:
            print(f"保存文件失败: {e}")
            return None
    
    def print_material_summary(self, materials, material_type):
        """
        打印素材摘要信息
        """
        print(f"\n=== {material_type.upper()} 素材摘要 ===")
        print(f"总数量: {len(materials)}")
        
        if material_type == "news":
            # 图文素材
            for i, item in enumerate(materials[:5], 1):  # 只显示前5个
                news_item = item.get('content', {}).get('news_item', [])
                if news_item:
                    print(f"{i}. 标题: {news_item[0].get('title', 'N/A')}")
                    print(f"   更新时间: {datetime.fromtimestamp(item.get('update_time', 0)).strftime('%Y-%m-%d %H:%M:%S')}")
        else:
            # 其他类型素材
            for i, item in enumerate(materials[:5], 1):  # 只显示前5个
                print(f"{i}. Media ID: {item.get('media_id', 'N/A')}")
                print(f"   文件名: {item.get('name', 'N/A')}")
                print(f"   更新时间: {datetime.fromtimestamp(item.get('update_time', 0)).strftime('%Y-%m-%d %H:%M:%S')}")
        
        if len(materials) > 5:
            print(f"   ... 还有 {len(materials) - 5} 个素材")

def main():
    """
    主函数 - 演示如何使用
    """
    wechat = WeChatMaterial()
    
    print("=== 微信订阅号永久素材管理工具 ===")
    print(f"AppID: {wechat.appid}")
    
    # 1. 获取素材总数统计
    print("\n1. 获取素材总数...")
    count_info = wechat.get_material_count()
    if count_info:
        print(f"素材统计: {json.dumps(count_info, ensure_ascii=False, indent=2)}")
    
    # 2. 获取各种类型的素材列表
    material_types = ["image", "voice", "video", "news"]
    
    for material_type in material_types:
        print(f"\n2. 获取{material_type}素材...")
        
        # 获取前20个素材
        materials = wechat.get_material_list(material_type, 0, 20)
        if materials and 'item' in materials:
            print(f"获取到 {len(materials['item'])} 个{material_type}素材")
            wechat.print_material_summary(materials['item'], material_type)
            
            # 保存到文件
            wechat.save_materials_to_file(materials['item'], material_type)
        else:
            print(f"未获取到{material_type}素材或发生错误: {materials}")
    
    # 3. 获取所有图片素材（如果需要）
    print(f"\n3. 获取所有图片素材...")
    all_images = wechat.get_all_materials("image")
    if all_images:
        wechat.save_materials_to_file(all_images, "image", "all_images.json")

if __name__ == "__main__":
    main()
